/* do not edit automatically generated by mc from CmdArgs.  */
/* CmdArgs.mod provides procedures to retrieve arguments from strings.

Copyright (C) 2001-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#define _CmdArgs_H
#define _CmdArgs_C

#   include "GASCII.h"
#   include "GStrLib.h"

#   define esc '\\'
#   define space ' '
#   define squote '\''
#   define dquote '"'
#   define tab ' '

/*
   GetArg - takes a command line and attempts to extract argument, n,
            from CmdLine. The resulting argument is placed into, a.
            The result of the operation is returned.
*/

extern "C" bool CmdArgs_GetArg (const char *CmdLine_, unsigned int _CmdLine_high, unsigned int n, char *Argi, unsigned int _Argi_high);

/*
   Narg - returns the number of arguments available from
          command line, CmdLine.
*/

extern "C" unsigned int CmdArgs_Narg (const char *CmdLine_, unsigned int _CmdLine_high);

/*
   GetNextArg - Returns true if another argument may be found.
                The argument is taken from CmdLine at position Index,
                Arg is filled with the found argument.
*/

static bool GetNextArg (const char *CmdLine_, unsigned int _CmdLine_high, unsigned int *CmdIndex, char *Arg, unsigned int _Arg_high);

/*
   CopyUntilSpace - copies characters until a Space character is found.
*/

static void CopyUntilSpace (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh);

/*
   CopyUntil - copies characters until the UntilChar is found.
*/

static void CopyUntil (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh, char UntilChar);

/*
   CopyChar - copies a character from string From to string To and
              takes into consideration escape characters. ie \x
              Where x is any character.
*/

static void CopyChar (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh);
static bool Escape (char ch);
static bool Space (char ch);
static bool DoubleQuote (char ch);
static bool SingleQuote (char ch);


/*
   GetNextArg - Returns true if another argument may be found.
                The argument is taken from CmdLine at position Index,
                Arg is filled with the found argument.
*/

static bool GetNextArg (const char *CmdLine_, unsigned int _CmdLine_high, unsigned int *CmdIndex, char *Arg, unsigned int _Arg_high)
{
  unsigned int ArgIndex;
  unsigned int HighA;
  unsigned int HighC;
  char CmdLine[_CmdLine_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (CmdLine, CmdLine_, _CmdLine_high+1);

  HighA = _Arg_high;  /* Index into Arg  */
  HighC = StrLib_StrLen ((const char *) CmdLine, _CmdLine_high);
  ArgIndex = 0;
  /* Skip spaces  */
  while (((*CmdIndex) < HighC) && (Space (CmdLine[(*CmdIndex)])))
    {
      (*CmdIndex) += 1;
    }
  if ((*CmdIndex) < HighC)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (SingleQuote (CmdLine[(*CmdIndex)]))
        {
          /* Skip over the single quote  */
          (*CmdIndex) += 1;
          CopyUntil ((const char *) CmdLine, _CmdLine_high, CmdIndex, HighC, (char *) Arg, _Arg_high, &ArgIndex, HighA, squote);
          (*CmdIndex) += 1;
        }
      else if (DoubleQuote (CmdLine[(*CmdIndex)]))
        {
          /* avoid dangling else.  */
          /* Skip over the double quote  */
          (*CmdIndex) += 1;
          CopyUntil ((const char *) CmdLine, _CmdLine_high, CmdIndex, HighC, (char *) Arg, _Arg_high, &ArgIndex, HighA, dquote);
          (*CmdIndex) += 1;
        }
      else
        {
          /* avoid dangling else.  */
          CopyUntilSpace ((const char *) CmdLine, _CmdLine_high, CmdIndex, HighC, (char *) Arg, _Arg_high, &ArgIndex, HighA);
        }
    }
  /* Skip spaces  */
  while (((*CmdIndex) < HighC) && (Space (CmdLine[(*CmdIndex)])))
    {
      (*CmdIndex) += 1;
    }
  if (ArgIndex < HighA)
    {
      Arg[ArgIndex] = ASCII_nul;
    }
  return (*CmdIndex) < HighC;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   CopyUntilSpace - copies characters until a Space character is found.
*/

static void CopyUntilSpace (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh)
{
  char From[_From_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (From, From_, _From_high+1);

  while ((((*FromIndex) < FromHigh) && ((*ToIndex) < ToHigh)) && (! (Space (From[(*FromIndex)]))))
    {
      CopyChar ((const char *) From, _From_high, FromIndex, FromHigh, (char *) To, _To_high, ToIndex, ToHigh);
    }
}


/*
   CopyUntil - copies characters until the UntilChar is found.
*/

static void CopyUntil (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh, char UntilChar)
{
  char From[_From_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (From, From_, _From_high+1);

  while ((((*FromIndex) < FromHigh) && ((*ToIndex) < ToHigh)) && (From[(*FromIndex)] != UntilChar))
    {
      CopyChar ((const char *) From, _From_high, FromIndex, FromHigh, (char *) To, _To_high, ToIndex, ToHigh);
    }
}


/*
   CopyChar - copies a character from string From to string To and
              takes into consideration escape characters. ie \x
              Where x is any character.
*/

static void CopyChar (const char *From_, unsigned int _From_high, unsigned int *FromIndex, unsigned int FromHigh, char *To, unsigned int _To_high, unsigned int *ToIndex, unsigned int ToHigh)
{
  char From[_From_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (From, From_, _From_high+1);

  if (((*FromIndex) < FromHigh) && ((*ToIndex) < ToHigh))
    {
      if (Escape (From[(*FromIndex)]))
        {
          /* Skip over Escape Character  */
          (*FromIndex) += 1;
        }
      if ((*FromIndex) < FromHigh)
        {
          /* Copy Normal Character  */
          To[(*ToIndex)] = From[(*FromIndex)];
          (*ToIndex) += 1;
          (*FromIndex) += 1;
        }
    }
}

static bool Escape (char ch)
{
  return ch == esc;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

static bool Space (char ch)
{
  return (ch == space) || (ch == tab);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

static bool DoubleQuote (char ch)
{
  return ch == dquote;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

static bool SingleQuote (char ch)
{
  return ch == squote;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   GetArg - takes a command line and attempts to extract argument, n,
            from CmdLine. The resulting argument is placed into, a.
            The result of the operation is returned.
*/

extern "C" bool CmdArgs_GetArg (const char *CmdLine_, unsigned int _CmdLine_high, unsigned int n, char *Argi, unsigned int _Argi_high)
{
  unsigned int Index;
  unsigned int i;
  bool Another;
  char CmdLine[_CmdLine_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (CmdLine, CmdLine_, _CmdLine_high+1);

  Index = 0;
  /* Continually retrieve an argument until we get the n th argument.  */
  i = 0;
  do {
    Another = GetNextArg ((const char *) CmdLine, _CmdLine_high, &Index, (char *) Argi, _Argi_high);
    i += 1;
  } while (! ((i > n) || ! Another));
  return i > n;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Narg - returns the number of arguments available from
          command line, CmdLine.
*/

extern "C" unsigned int CmdArgs_Narg (const char *CmdLine_, unsigned int _CmdLine_high)
{
  typedef struct Narg__T1_a Narg__T1;

  struct Narg__T1_a { char array[1000+1]; };
  Narg__T1 a;
  unsigned int ArgNo;
  char CmdLine[_CmdLine_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (CmdLine, CmdLine_, _CmdLine_high+1);

  ArgNo = 0;
  while (CmdArgs_GetArg ((const char *) CmdLine, _CmdLine_high, ArgNo, (char *) &a.array[0], 1000))
    {
      ArgNo += 1;
    }
  /* 
   IF ArgNo>0
   THEN
      DEC(ArgNo)
   END ;
  */
  return ArgNo;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void _M2_CmdArgs_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}

extern "C" void _M2_CmdArgs_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
